//
// Copyright (c) 2009 All Right Reserved
//
// vl
//
// 2009-01-01
// Contains ...
namespace LargoCommon.Music
{
using System;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Text;
using System.Xml.Linq;
using System.Xml.Serialization;
using Abstract;
using LargoCommon.Interfaces;
using Midi;
/// Musical tone.
/// Tone is defined in given bit Range with a given Loudness.
[Serializable]
[XmlRoot]
public sealed class MusicalPause : GeneralOwner, IMusicalTone
{
#region Fields and variables
///
/// Bar Number To.
///
private int barNumberTo;
////
//// Bit Range.
////
//// private BitRange bitRange;
#endregion
#region Constructors
/// Initializes a new instance of the MusicalPause class. Serializable.
public MusicalPause() {
}
/// Initializes a new instance of the MusicalPause class.
/// Rhythmical range of bits.
/// Number of musical bar.
public MusicalPause(
BitRange givenBitRange,
int barNumber) {
this.BitRange = givenBitRange;
this.BarNumber = barNumber;
this.ToneType = MusicalToneType.Empty;
this.Loudness = MusicalLoudness.None;
this.InstrumentNumber = (byte)MidiMelodicInstrument.None;
}
/// Initializes a new instance of the MusicalPause class.
/// Rhythmical order.
/// Musical duration.
/// Number of musical bar.
public MusicalPause(
byte givenRhythmicOrder,
byte givenDuration,
int barNumber) {
this.RhythmicOrder = givenRhythmicOrder;
this.Duration = givenDuration;
this.BarNumber = barNumber;
this.ToneType = MusicalToneType.Empty;
this.Loudness = MusicalLoudness.None;
this.InstrumentNumber = (byte)MidiMelodicInstrument.None;
}
///
/// Initializes a new instance of the class.
///
/// The xml element.
/// The rhythmic order.
public MusicalPause(XElement xelement, byte rorder) {
Contract.Requires(xelement != null);
this.BarNumber = XmlSupport.ReadIntegerAttribute(xelement.Attribute("Bar"));
this.BitFrom = XmlSupport.ReadByteAttribute(xelement.Attribute("Start")); ////BitFrom
this.Duration = XmlSupport.ReadByteAttribute(xelement.Attribute("Length"));
var br = new BitRange(rorder, this.BitFrom, (byte)this.Duration);
this.BitRange = br;
this.ToneType = MusicalToneType.Empty;
this.Loudness = MusicalLoudness.None;
//// 2019/11
//// this.InstrumentNumber = (byte)MidiMelodicInstrument.None;
var attrInstr = xelement.Attribute("Instrument");
if (attrInstr != null) {
this.InstrumentNumber = XmlSupport.ReadByteAttribute(attrInstr);
//// see lastInstrument ...
}
else {
this.InstrumentNumber = (int)MidiMelodicInstrument.None;
}
}
#endregion
#region Properties - Xml
///
/// Gets the get X element.
///
///
/// Property description.
///
public XElement GetXElement {
get {
var xe = new XElement(
"Pause",
new XAttribute("Bar", this.BarNumber),
new XAttribute("Start", this.BitFrom),
new XAttribute("Length", this.Duration));
return xe;
}
}
#endregion
#region Tone Properties
/// Gets or sets type of musical tone.
/// Property description.
public MusicalToneType ToneType { get; set; }
/// Gets or sets ordinal index of tone in musical track.
/// Property description.
public int OrdinalIndex { get; set; }
/// Gets or sets loudness.
/// Property description.
public MusicalLoudness Loudness { get; set; }
/// Gets or sets a value indicating whether property of musical tone.
/// Property description.
public bool IsReady { get; set; }
/// Gets a value indicating whether IsPause.
/// General musical property.
/// Returns value.
public bool IsPause => true;
///
/// Gets a value indicating whether this instance is empty.
///
///
/// true if this instance is empty; otherwise, false.
///
public bool IsEmpty => true;
/// Gets or sets bar number.
/// Property description.
public int BarNumber { get; set; }
/// Gets or sets bar number.
/// Property description.
public int BarNumberTo {
get => this.barNumberTo != 0 ? this.barNumberTo : this.BarNumber;
set => this.barNumberTo = value;
}
/// Gets or sets staff number (MusicXml).
/// Property description.
public byte RhythmicOrder { get; set; }
/// Gets or sets staff number (MusicXml).
/// Property description.
public int Duration { get; set; }
/// Gets or sets staff number (MusicXml).
/// Property description.
public byte Staff { get; set; }
/// Gets or sets voice number (MusicXml).
/// Property description.
public byte Voice { get; set; }
///
/// Gets or sets a value indicating whether this instance is from previous bar.
///
///
/// True if this instance is from previous bar; otherwise, false.
///
public bool IsFromPreviousBar { get; set; }
///
/// Gets or sets a value indicating whether [continue to next bar].
///
///
/// True if [continue to next bar]; otherwise, false.
///
public bool IsGoingToNextBar { get; set; }
/// Gets property of musical tone.
/// Property description.
public int BitPosition => ((this.BarNumber - 1) * this.RhythmicOrder) + this.BitFrom;
/// Gets or sets BitFrom.
/// Property description.
public byte BitFrom { get; set; }
/// Gets BitTo.
/// Property description.
public byte BitTo {
get {
var br = this.BitRange;
return br?.BitTo ?? 0;
}
}
/// Gets or sets index to harmonic structure.
/// Musical instrument.
///
/// Property description.
public byte InstrumentNumber { get; set; }
/// Gets or sets index to harmonic structure.
/// Property description.
public MidiChannel Channel { get; set; }
///
/// Gets or sets the bit range.
///
///
/// The bit range.
///
public BitRange BitRange {
get {
Contract.Ensures(Contract.Result() != null);
var bitRange = new BitRange(this.RhythmicOrder, this.BitFrom, (byte)this.Duration);
return bitRange;
}
set {
var bitRange = value;
if (bitRange == null) {
return;
}
this.RhythmicOrder = bitRange.Order;
this.BitFrom = bitRange.BitFrom;
this.Duration = bitRange.Length;
}
}
#endregion
#region Note Properties
///
/// Gets or sets the length of the note.
///
///
/// The length of the note.
///
public NoteLength NoteLength { get; set; }
#endregion
#region Other Properties
///
/// Gets the melodic identifier.
///
///
/// The melodic identifier.
///
public string MelodicIdentifier => $"Pause#{this.BitFrom}/{this.Duration}";
///
/// Gets the rhythmic identifier.
///
///
/// The rhythmic identifier.
///
public string RhythmicIdentifier => $"{this.BitFrom}/{this.Duration}";
#endregion
#region Static Factory Methods
///
/// Creates MusicalPause.
///
/// Rhythmical order.
/// Number of bit from.
/// Midi Duration.
/// Bar number.
/// Returns value.
public static MusicalPause CreatePause(byte rhythmicOrder, byte bitFrom, byte duration, int barNumber) {
if (duration <= 0) {
return null;
}
var bitRange = new BitRange(rhythmicOrder, bitFrom, duration);
var pause = new MusicalPause(bitRange, barNumber);
return pause;
}
#endregion
#region Public methods
/// Makes a deep copy of the MusicalStrike object.
/// Returns object.
public override object Clone() {
var mt = new MusicalPause(this.BitRange, this.BarNumber);
return mt;
}
/// Makes a deep copy of the MusicalStrike object.
/// Returns object.
public object CloneTone() {
var mt = new MusicalPause(this.BitRange, this.BarNumber);
return mt;
}
#endregion
#region Midi Support
///
/// Write real tone to midi collection.
///
/// Midi event collection.
/// Bar division.
public void WriteTo(MidiEventCollection midiEvents, int barDivision) {
if (midiEvents == null) {
return;
}
//// BitRange br = this.BitRange(this.BarNumber);
if (this.RhythmicOrder <= 0) {
return;
}
var duration = MusicalProperties.MidiDuration(this.RhythmicOrder, this.Duration, barDivision);
midiEvents.PutNote(0, 0, duration, (byte)MusicalLoudness.None, false, false); //// (byte)0,
}
///
/// Write Tone Events.
///
/// Midi events.
/// Bar division.
/// Delta Time of bit.
/// Delta Time of bar.
/// Delta Time Shift.
/// Returns value.
public bool WriteTo(MidiEventCollection midiEvents, int barDivision, int bitDuration, int barDuration, int deltaTimeShift) {
if (midiEvents == null) {
return false;
}
//// BitRange br = this.BitRange(this.BarNumber);
if (this.RhythmicOrder <= 0) {
return false;
}
var pause = this;
//// MusicalTone melTone = mtone as MusicalTone;
var bitRangeTo = pause.BitRange;
if (pause.RhythmicOrder <= 0 || bitRangeTo == null) {
return false;
}
var startTime = 1 + (barDuration * (pause.BarNumber - 1)) + (bitDuration * pause.BitFrom) - deltaTimeShift; //// lastTotalTime = 0
var barNumber2 = pause.BarNumberTo != 0 ? pause.BarNumberTo : pause.BarNumber;
if (barNumber2 <= 0) { //// 2016/10
return false;
}
var startTime2 = 1 + (barDuration * (barNumber2 - 1)) + (bitDuration * (bitRangeTo.BitTo + 1)) - deltaTimeShift;
if (startTime2 <= startTime) {
return false;
}
//// midiEvent = this.GetNoteOff(deltaTime2 - deltaTimeShift - 1); //// Temporary - decreased by 1, see comment on SortByStartTime
var duration = startTime2 - 1;
midiEvents.PutNote(0, 0, duration, (byte)MusicalLoudness.None, false, false); //// (byte)0,
return true;
}
#endregion
#region String representation
/// String representation of the object.
/// Returns value.
public string ToShortString() { //// virtual
var s = new StringBuilder();
s.Append(MusicalStrike.CPause);
s.Append(this.Duration);
return s.ToString();
}
/// String representation of the object.
/// Returns value.
public override string ToString() {
var s = new StringBuilder(string.Empty);
s.AppendFormat(CultureInfo.CurrentCulture, "{0,3}", MusicalStrike.CPause);
//// for (byte lev = 2; lev <= this.Duration; lev++) {
//// s.AppendFormat(CultureInfo.CurrentCulture, "{0,3}", MusicalStrike.CRepeat); }
s.AppendFormat(" <{0,3}>", this.Duration);
//// s.Append(",lev" + Loudness.ToString(System.Globalization.CultureInfo.CurrentCulture.NumberFormat) + ")");
//// s.Append(base.ToString());
return s.ToString();
}
#endregion
}
}